* Faculty naive recursive version

#+BEGIN_SRC python :results output
def fac(n):
    # define a base case, to make sure the recursion stops at the desired point
    if n == 1:
        return 1
    # recursive call! calculate the next argument from the previous argument! at
    # some point in a future function execution, the value will be at 1,
    # assuming, that you gave this function initially a positive number (edge
    # case: fac(negative number))
    return n * fac(n - 1)

print(fac(10))
#+END_SRC

#+RESULTS:
: 3628800

* Faculty tail-recursive version

#+BEGIN_SRC python :results output
def fac(n):
    # this inner function is often called "iter". it is only visible inside
    # fac. it receives as second argument `n`, which shadows the `n` argument of
    # fac.
    def iter(current_val, n):
        # define a base case, to make sure the recursion stops at the desired point
        if n == 1:
            # note, that we return the accumulated value, not 1, in the base
            # case
            return current_val
        # here is the idea: accumulate the result and give it as argument as
        # well! this could also be done in the outer function fac, but that
        # would require the user to give more arguments than expected to the
        # function fac.
        return iter(current_val * n, n - 1)
    # start with 1 again, the neutral element of multiplication
    return iter(1, n)

print(fac(10))
#+END_SRC

#+RESULTS:
: 3628800
